package com.jianqiao.delivery.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jianqiao.delivery.delivery.domain.DeliveryEntity;
import com.jianqiao.delivery.delivery.service.DeliveryService;
import com.jianqiao.delivery.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * author: cyx
 * create: 2024/10/18 15:46
 **/
@Slf4j
@Component
public class OrderSchedulerInitializer {

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private DeliveryService deliveryService;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);

    private Map<String ,ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();

    private List<Object> getRedisOrderList() {
        List<Object> unpaidOrderList = new ArrayList<>();
        List<String> scanList = redisUtils.scan("expressUnpaidOrder-*");
        for (String s : scanList) {
            Object object = redisUtils.get(s);
            unpaidOrderList.add(object);
        }
        return unpaidOrderList;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationEvent() {
        List<Object> redisOrderList = getRedisOrderList();
        for (Object object : redisOrderList) {
            Map<? ,?> map = (Map<? ,?>) object;
            String orderId = map.get("orderId").toString();
            String createTime = map.get("createTime").toString();
            Runnable checkTask = createCheckTask(orderId, createTime);
            ScheduledFuture<?> scheduledFuture = scheduler.scheduleWithFixedDelay(checkTask ,0 ,60 , TimeUnit.SECONDS);
            scheduledFutureMap.put(orderId ,scheduledFuture);
        }
    }

    private Runnable createCheckTask(String orderId ,String createTimeStr) {
        return () -> {
            log.info("Restart the timer for " + orderId);
            long expirationTimeInSeconds = 1800;
            LocalDateTime now = LocalDateTime.now();

            //从redis或数据库中查询该订单的状态是否为0-未支付
            String orderPayStatus = "";
            boolean hasKey = redisUtils.hasKey(orderId + "-orderPayStatus");
            if (hasKey){
                orderPayStatus = redisUtils.get(orderId + "-orderPayStatus").toString();
            }
            else {
                LambdaQueryWrapper<DeliveryEntity> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(DeliveryEntity::getId ,orderId);
                orderPayStatus = deliveryService.getOne(queryWrapper).getPayment().toString();
                redisUtils.set(orderId + "-orderPayStatus" ,orderPayStatus ,1800);
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date createTime = null;
            try {
                createTime = dateFormat.parse(createTimeStr);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
//            Date createTime = order.getCreateTime();
            LocalDateTime localDateTime = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            LocalDateTime expirationTime = localDateTime.plusSeconds(expirationTimeInSeconds);
            //判断是否为未支付订单并且是否过期
            boolean nowAfter = now.isAfter(expirationTime);
            boolean equals = "0".equals(orderPayStatus);
            if (nowAfter && equals) {
                //订单过期   修改状态
                log.info("Find the order(" + orderId + ") is timeout and unpaid.Let close the order and timer.");
                LambdaUpdateWrapper<DeliveryEntity> updateStatusWrapper = new LambdaUpdateWrapper<>();
                updateStatusWrapper.set(DeliveryEntity::getStatus ,-2)
                        .eq(DeliveryEntity::getId ,orderId);
                deliveryService.update(updateStatusWrapper);
                log.info("订单过期");
                //清除Redis中unpaidOrderList过期的orderId
                redisUtils.del("expressUnpaidOrder-" + orderId);
                //关闭定时器
                boolean cancelFlag = scheduledFutureMap.remove(orderId).cancel(true);
//                boolean cancelFlag = scheduledFuture.cancel(true);
                if (cancelFlag == true) {
                    log.info("The timer for " + orderId + " had close.");
                }
            }
            if (!("0".equals(orderPayStatus))) {
                log.info("The order(" + orderId + ") status is other value.Let close the timer.");
                //关闭定时器
//                scheduledFuture.cancel(true);
                boolean cancelFlag = scheduledFutureMap.remove(orderId).cancel(true);
            }
        };
    }
}
